package com.lxl.service;

import com.lxl.config.SystemConfig;
import com.lxl.config.TaskStatus;
import com.lxl.pojo.InterfaceMonitor;
import com.lxl.rabbitmq.MessageSender;
import com.lxl.redis.JedisConfig;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class InterfaceMonitorService {

    @Autowired
    private MessageSender messageSender;

    private Session session = null;

    private static Configuration configuration;
    private static SessionFactory factory;

    private static ExecutorService executor = Executors.newFixedThreadPool(18);

    static {
        configuration = new Configuration().configure();
        factory = configuration.buildSessionFactory();
    }

    private InterfaceMonitorService() {
        this.session = factory.openSession();
    }

    public static InterfaceMonitorService createInstance() {
        return new InterfaceMonitorService();
    }

    /**
     * 保存日志操作
     *
     * @param interfaceMonitor 日志信息
     * @param updateFlag       是否修改
     */
    public void saveOrUpdateLog(InterfaceMonitor interfaceMonitor, boolean updateFlag) {
        //获取Redis中日志打印模式
        String logKey = new StringBuilder("log").append("_").append(interfaceMonitor.getInterfaceCategory()).
                append("_").append(interfaceMonitor.getInterfaceName()).toString();
        String logType = SystemConfig.PROC_LOG;
        Jedis jedis = null;
        try {
            jedis = JedisConfig.getJedis();
            logType = jedis.get(logKey);
        } catch (Exception e) {
            e.printStackTrace();
            logType = SystemConfig.PROC_LOG;
        } finally {
            if (null != jedis) {
                jedis.close();
            }
        }
        switch (logType) {
            case SystemConfig.DEBUG_LOG:
                if (updateFlag) {
                    update(interfaceMonitor);
                } else {
                    insert(interfaceMonitor);
                }
                break;
            case SystemConfig.PROC_LOG:
                //记录所有日志，忽略输出参数字段
                interfaceMonitor.setOutputData(null);
                messageSender.sendMessage(SystemConfig.QUEUE_PROC_NAME, concatMessage(interfaceMonitor));
                break;
            case SystemConfig.SIMPLE_LOG:
                //只记录执行失败日志
                if (StringUtils.equals(String.valueOf(TaskStatus.ERROR), String.valueOf(interfaceMonitor.getStatus()))) {
                    messageSender.sendMessage(SystemConfig.QUEUE_SIMPLE_NAME, concatMessage(interfaceMonitor));
                }
                break;
            default:
                break;
        }
    }

    /**
     * 异步执行保存日志操作
     *
     * @param interfaceMonitor
     */
    public void asyncSaveLog(InterfaceMonitor interfaceMonitor) {
        //获取Redis中日志打印模式
        String logKey = new StringBuilder("log").append("_").append(interfaceMonitor.getInterfaceCategory()).
                append("_").append(interfaceMonitor.getInterfaceName()).toString();
        String logType = SystemConfig.PROC_LOG;
        Jedis jedis = null;
        try {
            jedis = JedisConfig.getJedis();
            logType = jedis.get(logKey);
        } catch (Exception e) {
            e.printStackTrace();
            logType = SystemConfig.PROC_LOG;
        } finally {
            if (null != jedis) {
                jedis.close();
            }
        }
        switch (logType) {
            case SystemConfig.DEBUG_LOG:
                executor.submit(() -> insert(interfaceMonitor));
                break;
            case SystemConfig.PROC_LOG:
                //记录所有日志，忽略输出参数字段
                interfaceMonitor.setOutputData(null);
                executor.submit(() -> messageSender.sendMessage(SystemConfig.QUEUE_PROC_NAME, concatMessage(interfaceMonitor)));
                break;
            case SystemConfig.SIMPLE_LOG:
                //只记录执行失败日志
                if (StringUtils.equals(String.valueOf(TaskStatus.ERROR), String.valueOf(interfaceMonitor.getStatus()))) {
                    executor.submit(() -> messageSender.sendMessage(SystemConfig.QUEUE_SIMPLE_NAME, concatMessage(interfaceMonitor)));
                }
                break;
            default:
                break;
        }
    }

    /**
     * 拼接消息队列信息
     *
     * @param interfaceMonitor
     * @return
     */
    private String concatMessage(InterfaceMonitor interfaceMonitor) {
        StringBuffer message = new StringBuffer();
        message.append("接口类型:").append(interfaceMonitor.getInterfaceCategory()).append(" ");
        message.append("接口执行名称:").append(interfaceMonitor.getInterfaceName()).append(" ");
        message.append("访问IP:").append(interfaceMonitor.getVisitIP()).append(" ");
        message.append("访问时间:").append(interfaceMonitor.getVisitTime()).append(" ");
        message.append("输入参数:").append(interfaceMonitor.getInputParam()).append(" ");
        message.append("输出参数:").append(interfaceMonitor.getOutputData()).append(" ");
        message.append("接口耗时:").append(interfaceMonitor.getTimeConsuming()).append("ms ");
        message.append("执行状态:").append(TaskStatus.TASK_STATUS_MAP.get(interfaceMonitor.getStatus())).append(" ");
        message.append("备注:").append(interfaceMonitor.getNote());
        return message.toString();
    }

    public void insert(InterfaceMonitor interfaceMonitor) {
        Transaction tran = session.beginTransaction();
        session.save(interfaceMonitor);
        tran.commit();
        session.close();
    }

    private void update(InterfaceMonitor interfaceMonitor) {
        Transaction tran = session.beginTransaction();
        session.update(interfaceMonitor);
        tran.commit();
        session.close();
    }
}
